<?php
/**
 * Description of SelectQuery
 *
 * @author d.chechotkin
 */
class SelectQuery { //implements SelectQueryInterface {

    protected $table = array();
    protected $where = array();
    protected $joins = array();
    protected $columns = array();
    protected $order = null;
    protected $limit = null;

    public function __constrict(string $table = null, string $as = null) {
        if ($table == null) return;
        if ($as == null) return;
        $this->table[$table] = $as;
    }

    public function columns(array $list) {
        foreach($list as $column=>$as) {
            if (!is_int($column)) $this->column($column, $as);
            else $this->column($as);
        }
    }

    public function column(dbfield $column, $as = null) {
        if (!$column) return;
        if ($as == null) $as = $column;
        $this->columns[$column] = $as;
    }

    public function cross_join(string $table, string $on = null, mixed $params = null, string $as = null) {
        $this->joins[] = array(
                'type' => 'CROSS JOIN',
                'table' => $table,
                'as' => $as,
                'on'    => $on,
                'params' => $params
        );
    }

    public function join(string $table, string $on = null, mixed $params = null) {
        $this->joins[] = array(
                'type' => 'JOIN',
                'table' => $table,
                'on'    => $on,
                'params' => $params
        );
    }
    public function left_join(string $table, string $on = null, mixed $params = null) {
        $this->joins[] = array(
                'type' => 'LEFT JOIN',
                'table' => $table,
                'on'    => $on,
                'params' => $params
        );
    }
    public function limit(integer $count) {
        $this->limit = $count;
    }
    public function order(dbfield $field, string $order = null) {
        $this->order[0] = $order;
        $this->order[] = mysqli_escape_string($field);
    }
    public function right_join(string $table, string $on = null, mixed $params = null) {
        Log::fatal('Right join is not supported by MySQL');
    }
    public function where(string $where, mixed $params = null, string $after = null) {
        if (!in_array(trim(strtolower($after)), array('and', 'or'))) {
            $after = 'AND';
        }
        $this->where[] = array(
                'base' => $where,
                'params' => $params,
                'after' => $after
        );
    }

    public function assembly() {
        $query  = 'SELECT ';
        if (count($this->columns) == 0) $this->columns[] = '*';
        $query .= implode(', ', $this->columns);
        $query .= ' FROM';
        $keys = array_keys($this->table);
        for($i=0;$i<count($keys);$i++) {
            $key = $keys[$i];
            $val = $this->table[$key];

            if ($key == $val) {
                $query .= " $val";
            } else {
                $query .= " $key as $val";
            }
        }
        foreach($this->joins as $join) {
            $query .= ' '.$join['type'].' ';
            $query .= ' '.$join['table'].' ';
            $join['on'] = sprintf($join['on'], $join['params']);
            $query .= ' ON '.$join['on'].' ';
        }

        if (count($this->where) > 0) {
            $query .= ' WHERE ';
            foreach ($this->where as $where) {
                $query .= sprintf($where['base'], $where['params']).' '.$where['after'];
            }
            $query .= ' TRUE ';
        }
        if ($this->order != null) {
            $order = array_shift($this->order);
            $query .= ' ORDER BY '.implode(', ', $this->order).' '.$order.' ';
        }

        if (is_array($this->limit)) {
            $query .= ' LIMIT '.$this->limit['limit'].', '.$this->limit['from'];
        } else if ($this->limit != null) {
            $query .= ' LIMIT '.$this->limit;
        }

        return $query;

    }
    
    public function from(string $table, string $as = null) {
        if (!$as) $as = $table;
        $this->table[$table] = $as;
    }

    public function part(integer $from, integer $limit = null) {
        $this->limit['from'] = $from;
        $this->limit['limit'] = $limit;
    }

}
?>
